<template>
  <uploader
      :options="options"
      :fileStatusText="fileStatusText"
      class="uploader-example"
      ref="uploaderRef"
      @file-complete="fileComplete"
      @complete="complete"
      :onFileAdded="onFileAdded"
      :onFilesAdded="onFilesAdded"
  >
    <uploader-unsupport></uploader-unsupport>
    <uploader-drop>
      <p>拖动文件到这里上传</p>
      <uploader-btn>选择文件</uploader-btn>
      <!--      <uploader-btn :attrs="attrs">select images</uploader-btn>-->
      <!--      <uploader-btn :directory="true">选择文件夹</uploader-btn>-->
    </uploader-drop>
    <uploader-list></uploader-list>
  </uploader>
</template>

<script>
import {nextTick, ref, onMounted} from 'vue'
import SparkMD5 from 'spark-md5'
import axios from 'axios'

export default {
  setup() {
    const uploaderRef = ref(null)
    const CHUNK_SIZE = 20 * 1024 * 1024;
    const options = {
      // 上传地址
      target: 'http://localhost:8080/file/upload', //
      // 是否开启服务器分片校验。默认为 true
      testChunks: true,
      // 真正上传的时候使用的 HTTP 方法,默认 POST
      uploadMethod: "POST",
      // 分片大小
      chunkSize: CHUNK_SIZE,
      // 并发上传数，默认为 3
      simultaneousUploads: 3,
      /**
       * 判断分片是否上传，秒传和断点续传基于此方法
       * 这里根据实际业务来 用来判断哪些片已经上传过了 不用再重复上传了 [这里可以用来写断点续传！！！]
       */
      checkChunkUploadedByResponse: (chunk, message) => {
        // message是后台返回
        let messageObj = JSON.parse(message);
        let dataObj = messageObj.data;
        if (dataObj.uploaded !== undefined) {
          return dataObj.uploaded;
        }
        // 判断文件或分片是否已上传，已上传返回 true
        // 这里的 uploadedChunks 是后台返回]
        return (dataObj.uploadedChunks || []).indexOf(chunk.offset + 1) >= 0;
      },
      //格式化时间
      parseTimeRemaining: function (timeRemaining, parsedTimeRemaining) {
        return parsedTimeRemaining
            .replace(/\syears?/, "年")
            .replace(/\days?/, "天")
            .replace(/\shours?/, "小时")
            .replace(/\sminutes?/, "分钟")
            .replace(/\sseconds?/, "秒");
      },
    }
    // 修改上传状态
    const fileStatusText = {
      success: "上传成功",
      error: "上传错误",
      uploading: "正在上传",
      paused: "停止上传",
      waiting: "等待中",
    }
    //单文件上传
    const onFileAdded = (file) => {
      //校验文件md5
      computeMD5(file);
    }
    const onFilesAdded = (files, fileList) => {
      console.log("files:", files, "--fileList:", fileList)
      for (let i = 0; i < files.length; i++) {
        computeMD5(files[i]);
      }
    }
    const complete = () => {
      console.log('complete', arguments)
    }
    //分片上传完成后调用合并接口
    const fileComplete = (rootFile) => {
      console.log("rootFile:", rootFile)
      axios.post("http://localhost:8080/file/merge", {
        filename: rootFile.name,
        totalSize: rootFile.size,
        identifier: rootFile.uniqueIdentifier
      }).then(function (response) {
        console.log(response)
      }).catch(function (error) {
        console.log(error)
      });
    }

    //MD5加密分片
    function computeMD5(file) {
      let fileReader = new FileReader();
      let time = new Date().getTime();
      let blobSlice =
          File.prototype.slice ||
          File.prototype.mozSlice ||
          File.prototype.webkitSlice;
      let currentChunk = 0;
      let chunks = Math.ceil(file.size / CHUNK_SIZE);
      let spark = new SparkMD5.ArrayBuffer();
      // 文件状态设为"计算MD5"
      file.cmd5 = true; //文件状态为“计算md5...”
      file.pause();
      loadNext();
      fileReader.onload = (e) => {
        spark.append(e.target.result);
        if (currentChunk < chunks) {
          currentChunk++;
          loadNext();
          // 实时展示MD5的计算进度 , 开始第${currentChunk + 1} / ${chunks}分片解析
          console.log(`第${currentChunk}分片解析完成`);
        } else {
          let md5 = spark.end();
          console.log(
              `MD5计算完毕：${file.name} \nMD5：${md5} \n分片：${chunks} 大小:${file.size} 用时：${new Date().getTime() - time} ms`
          );
          spark.destroy(); //释放缓存
          file.uniqueIdentifier = md5; //将文件md5赋值给文件唯一标识
          file.cmd5 = false; //取消计算md5状态
          file.resume(); //开始上传
        }
      };
      fileReader.onerror = function () {
        this.error(`文件${file.name}读取出错，请检查该文件`);
        file.cancel();
      };

      function loadNext() {
        let start = currentChunk * CHUNK_SIZE;
        let end =
            start + CHUNK_SIZE >= file.size ? file.size : start + CHUNK_SIZE;
        fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end));
      }
    }

    onMounted(() => {
      nextTick(() => {
        window.uploader = uploaderRef.value.uploader
      })
    })
    return {
      uploaderRef,
      options,
      fileStatusText,
      complete,
      fileComplete,
      onFileAdded,
      onFilesAdded
    }
  }
}
</script>

<style>
.uploader-example {
  width: 880px;
  padding: 15px;
  margin: 40px auto 0;
  font-size: 12px;
  box-shadow: 0 0 10px rgba(0, 0, 0, .4);
}

.uploader-example .uploader-btn {
  margin-right: 4px;
}

.uploader-example .uploader-list {
  max-height: 440px;
  overflow: auto;
  overflow-x: hidden;
  overflow-y: auto;
}
</style>
